/*
	Written By Pradipna Nepal
	www.pradsprojects.com

	Copyright (C) 2011 Prads Projects
	Please read COPYING.txt included along with this source code for more detail.
	If not included, see http://www.gnu.org/licenses/
*/

#include <windows.h>

//For checking Memory leaks, must be erased while building a release version
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

#include "resource.h"
#include "libGUIFunctions.h"
#include "libEmulator.h"
#include "libDebugger.h"
using namespace GUIFunctions;
using namespace Emulator;
using namespace Debugger;

//GUI Theme
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' \"\"version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

const char WndCN[] = "C16IDEWCN";

//Toolbar bitmaps
HBITMAP tbBitmaps[NUM_OF_TB_BTNS];
//Font for IDE
HFONT controlsFont;

HWND hwndEmu;	//Emulator HWND

void releaseMemory();

LRESULT CALLBACK WndProc(HWND hwnd, UINT msG, WPARAM wParam, LPARAM lParam) {
	switch (msG) {
		case WM_CREATE:
			createControls(hwnd, tbBitmaps, &controlsFont);
			hwndEmu = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_EMU_DIALOG), hwnd,
				emuWndProc);
			hwndDebug = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DBG_DIALOG),
				hwndEmu, debugWndProc);
			break;
		case WM_COMMAND:
			switch (LOWORD(wParam)) {
				case IDC_MENU_COMPILE_RUN:
					if (!startEmulation) {
						ShowWindow(hwndEmu, SW_SHOW);
						cpu = new CPUCore(hwndEmu, &startEmulation);
						if (!startEmulation) SendMessage(hwndEmu, WM_CLOSE, 0, 0);
					}
					break;
				case IDC_MENU_COMPILE_DEBUG:
					if (startEmulation) {
						sendInitMessageToDebugger();
						ShowWindow(hwndDebug, SW_SHOW);
						startDebug = true;
					}
			}
			break;
		case WM_SIZE:
			resizeControls(hwnd, LOWORD(lParam), HIWORD(lParam));
			break;
		case WM_CLOSE:
			DestroyWindow(hwnd);
			break;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		default:
			return DefWindowProc(hwnd, msG, wParam, lParam);
	}
	return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
	//To check memory leaks, must be erased while building a release version
	_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

	WNDCLASSEX wCEx;

	ZeroMemory(&wCEx, sizeof(wCEx));
	wCEx.cbSize = sizeof(WNDCLASSEX);
	wCEx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
	wCEx.hCursor = LoadCursor(NULL, IDC_ARROW);
	wCEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wCEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
	wCEx.hInstance = hInstance;
	wCEx.lpfnWndProc = WndProc;
	wCEx.lpszClassName = WndCN;
	wCEx.lpszMenuName = MAKEINTRESOURCE(IDM_MAIN_MENU);

	if (!RegisterClassEx(&wCEx)) {
		MessageBox(NULL, "Error Registering Window Class", "Error", MB_ICONERROR);
		return 0;
	}

	HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WndCN, "Chip16 IDE", 
		WS_OVERLAPPEDWINDOW, 100, 100, 700, 550, NULL, NULL, NULL, NULL);

	if (hwnd == NULL) {
		MessageBox(NULL, "Error Creating Window", "Error", MB_ICONERROR);
		return 0;
	}

	ShowWindow(hwnd, nShowCmd);
	UpdateWindow(hwnd);

	MSG Msg;

	while (true) {
		if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) {
			if (Msg.message == WM_QUIT) break;
			if (Msg.message == WM_KEYDOWN && startDebug) {	//Key Down Hook for Debug Dialog
				SendMessage(hwndDebug, WM_KEYDOWN, Msg.wParam, Msg.lParam);
				continue;
			}
			TranslateMessage(&Msg);
			DispatchMessage(&Msg);
		}
		if (startEmulation && !startDebug) cpu->fetchDecodeExecute();
	}

	releaseMemory();

	return 0;
}

void releaseMemory() {
	for (int i = 0; i < NUM_OF_TB_BTNS; ++i) DeleteObject(tbBitmaps[i]);
	DeleteObject(controlsFont);
}